package com.fly.docker.web;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.PostConstruct;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.fly.core.entity.JsonResult;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.spotify.docker.client.DefaultDockerClient;
import com.spotify.docker.client.DockerCertificates;
import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.exceptions.DockerCertificateException;
import com.spotify.docker.client.exceptions.DockerException;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("/dockerClients")
@Api(tags = "docker客户端接口")
public class DockerClientApi
{
    List<DockerClient> dockerClients = new ArrayList<>();
    
    @ApiOperation("注册Docker")
    @ApiOperationSupport(order = 10)
    @ApiImplicitParam(name = "url", value = "docker服务地址", example = "118.178.86.130:2375", required = true)
    @PostMapping(value = "/envInit", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public JsonResult<?> envInit(String url, MultipartFile[] files)
    {
        if (StringUtils.isBlank(url) || files == null || files.length != 3)
        {
            return JsonResult.error("docker服务地址、ca证书、客户端证书或客户端私钥不能为空");
        }
        try
        {
            String subDir = "/docker_ca/" + StringUtils.trimToEmpty(url).replace(":", "_");
            for (MultipartFile file : files)
            {
                try (InputStream is = file.getInputStream())
                {
                    // 原始文件名
                    FileUtils.copyInputStreamToFile(is, new File(subDir, file.getOriginalFilename()));
                }
            }
            // TLS初始化
            DockerClient dockerclientTsl = DefaultDockerClient.builder().uri(URI.create("https://" + url)).dockerCertificates(new DockerCertificates(Paths.get(subDir))).build();
            if (StringUtils.equals(dockerclientTsl.ping(), "OK"))
            {
                dockerClients.add(dockerclientTsl);
                return JsonResult.success("初始化合作方docker成功");
            }
        }
        catch (IOException | DockerCertificateException | DockerException | InterruptedException e)
        {
            log.error(e.getMessage());
            return JsonResult.error("初始化出错，请检查docker服务地址、ca证书、客户端证书或客户端私钥是否合法");
        }
        return JsonResult.error("初始化合作方docker出错");
    }
    
    @ApiOperation("获取DockerClients")
    @ApiOperationSupport(order = 20)
    @GetMapping("/getRemoteDockers")
    public JsonResult<?> getRemoteDockers()
    {
        List<String> hosts = dockerClients.stream().map(d -> d.getHost()).filter(host -> !StringUtils.contains(host, "localhost")).collect(Collectors.toList());
        return JsonResult.success(hosts, "获取合作方DockerClients成功");
    }
    
    @PostConstruct
    private void initDockers()
    {
        try
        {
            Arrays.stream(new File("/docker_ca").listFiles()).filter(File::isDirectory).map(File::getAbsolutePath).forEach(path -> initDocker(path));
        }
        catch (Exception e)
        {
            log.error(e.getMessage());
        }
    }
    
    /**
     * 初始化DockerClient
     * 
     * @param path
     * @see [类、类#方法、类#成员]
     */
    private void initDocker(String path)
    {
        String url = new File(path).getName().replace("_", ":");
        try
        {
            // TLS
            log.info("###### will init docker for https://{} by {}", url, path);
            DockerClient dockerclient = DefaultDockerClient.builder().uri(URI.create("https://" + url)).dockerCertificates(new DockerCertificates(Paths.get(path))).build();
            if (StringUtils.equals(dockerclient.ping(), "OK"))
            {
                dockerClients.add(dockerclient);
            }
        }
        catch (DockerCertificateException | DockerException | InterruptedException e)
        {
            log.error(e.getMessage());
        }
    }
}
